package net.zoneland.greenleaf.common.worktimehelper;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import net.zoneland.greenleaf.common.date.DateOperation;
import net.zoneland.greenleaf.system.entity.Sys_holidayconf;

import org.apache.log4j.Logger;


/**
 * TimeForDayManager 功能： 计算一天工作时间
 * 
 * 1、需要考虑上班开始时间，结束时间，可以自定义 2、需要考虑一天中午的休息时间，可以自定义
 * 
 * @作者 liyi
 */
public class TimeForDayManager {
	
	public static Logger logger = Logger.getLogger(TimeForDayManager.class);
	/**
	 * 开始工作时间， 如：08:30:00
	 */
	private String startWorkTime = null;
	/**
	 * 结束工作时间， 如：17:30:00
	 */
	private String endWorkTime = null;
	/**
	 * 休息时间短， 如：List<TimeQuantumOfDay>
	 */
	private List<Sys_holidayconf> forRestTimeQuantumOfDay_List = null;
	
	private DateOperation dateOperation = new DateOperation();

	/**
	 * 对象构造方法
	 * 
	 * @param startWorkTime
	 *            开始工作时间， 如：08:30:00
	 * @param endWorkTime
	 *            结束工作时间， 如：17:30:00
	 * @param forRestTimeQuantumOfDay_List
	 *            <TimeQuantumOfDay> 休息时间段
	 */
	public TimeForDayManager(String startWorkTime, String endWorkTime, List<Sys_holidayconf> forRestTimeQuantumOfDay_List) {
		try{
			dateOperation.getDeff("00:00:00", startWorkTime);
			this.startWorkTime = startWorkTime;
		}catch(Exception e){
			logger.error("TimeForDayManager对象实例化，传入的参数startWorkTime格式不正确，startWorkTime：" + startWorkTime);
			this.startWorkTime = "08:30:00";
		}
		
		try{
			dateOperation.getDeff("00:00:00", endWorkTime);
			this.endWorkTime = endWorkTime;
		}catch(Exception e){
			logger.error("TimeForDayManager对象实例化，传入的参数endWorkTime格式不正确，endWorkTime：" + endWorkTime);
			this.endWorkTime = "17:30:00";
		}
		
		if( forRestTimeQuantumOfDay_List == null ){
			this.forRestTimeQuantumOfDay_List = new ArrayList<Sys_holidayconf>();
		}else{
			this.forRestTimeQuantumOfDay_List = forRestTimeQuantumOfDay_List;
		}
		
	}

	/**
	 * 功能： 计算当天还剩余多少工作时间（分钟数）
	 * 
	 * @param dateString
	 * @return
	 * @throws ParseException
	 */
	public long getWorkTimeLeftOfDay(String dateString) throws ParseException {
		// 计算一个工作日总共有多少分钟。
		long maxWorkTime = 0, usedWorkTime = 0;
		maxWorkTime = getMaxWorkTimeAsMinutes(startWorkTime, endWorkTime);
		usedWorkTime = getWorkTimeUsedOfDay(dateString);
		if(usedWorkTime<0){
			usedWorkTime = 0;
		}
		return maxWorkTime - usedWorkTime;
	}

	/**
	 * 功能： 计算当天已经使用多少工作时间（分钟数）
	 * 
	 * @param dateString
	 * @return 1、先计算当前的时间是当天的第几分钟 2、再计算当前的多少分钟是工作时间之前的时间 如果当前的时间（分钟）<工作时间之前的时间（分钟），那么今天使用0分钟
	 *         如果当前的时间（分钟）>工作时间之前的时间（分钟），那么 今天使用的(分钟) = 当前的时间（分钟） -
	 *         工作时间之前的时间（分钟） 3、计算一天的最大工作时间（分钟）
	 *         如果今天使用的(分钟)>一天的最大工作时间（分钟），那么今天使用的(分钟)=一天的最大工作时间（分钟）
	 * @throws ParseException
	 */
	public long getWorkTimeUsedOfDay(String dateString) throws ParseException {
		Calendar calendar_date = Calendar.getInstance();
		Date date = null;
		long hours = 0, minutes = 0, usedMinutes = 0;
		long maxWorkTime = 0, beforeWorkTime = 0;
		try{
			date = DateFormatUtil.FORMAT.parse(dateString);
			calendar_date.setTime(date);
		}catch(Exception e){
			logger.error("日期格式化异常：dateString=" + dateString);
			date = new Date();
			calendar_date.setTime(date);
		}	
		hours = calendar_date.get(Calendar.HOUR_OF_DAY);
		minutes = calendar_date.get(Calendar.MINUTE);
		maxWorkTime = getMaxWorkTimeAsMinutes(startWorkTime, endWorkTime);
		beforeWorkTime = dateOperation.getDeff("00:00:00", startWorkTime);
		
		usedMinutes = hours * 60 + minutes - beforeWorkTime;

		// 判断已经工作的时间中是否已经包括了休息时间段
		if (this.forRestTimeQuantumOfDay_List != null
				&& this.forRestTimeQuantumOfDay_List.size() > 0) {
			Sys_holidayconf timeQuantumOfDay = null;
			Date timeQuantumOfDay_startDate = null;
			Date timeQuantumOfDay_endDate = null;
			for (int i = 0; i < forRestTimeQuantumOfDay_List.size(); i++) {
				timeQuantumOfDay = (Sys_holidayconf) forRestTimeQuantumOfDay_List.get(i);
				try{
					timeQuantumOfDay_startDate = DateFormatUtil.FORMAT.parse(DateFormatUtil.FORMAT_DATE.format(date) + " " + timeQuantumOfDay.getStarttime());
				}catch(Exception e){
					logger.error("系统在尝试将日期字符串转换为日期格式时发生异常，timeQuantumOfDay_startDate字符串格式：" + DateFormatUtil.FORMAT_DATE.format(date) + " " + timeQuantumOfDay.getStarttime(), e);
				}
				
				try{
					timeQuantumOfDay_endDate = DateFormatUtil.FORMAT.parse(DateFormatUtil.FORMAT_DATE.format(date) + " "+ timeQuantumOfDay.getEndtime());
				}catch(Exception e){
					logger.error("系统在尝试将日期字符串转换为日期格式时发生异常，timeQuantumOfDay_endDate字符串格式：" + DateFormatUtil.FORMAT_DATE.format(date) + " " + timeQuantumOfDay.getStarttime(), e);
				}
				
				if (timeQuantumOfDay_startDate.before(calendar_date.getTime())) {
					// 如果时间段在当前时间点之前
					// 看看是否包括整个时间段，看看时间段的结束时间是否也包括在当前时间之前？
					if (timeQuantumOfDay_endDate.before(calendar_date.getTime())) {
						// 那么，要从已经使用的时间中 完全减去 时间段持续的时间
						usedMinutes = usedMinutes - dateOperation.getDeff(timeQuantumOfDay.getStarttime(), timeQuantumOfDay.getEndtime());
					} else {
						// 当前时间刚好在休息时间之间
						// 已经使用的时间应该减去休息时间到当前时间段的持续时间
						usedMinutes = usedMinutes - dateOperation.getDeff(timeQuantumOfDay.getStarttime(), DateFormatUtil.FORMAT_TIME.format(date));
					}
				}
			}
		}
		if(usedMinutes<0){
			usedMinutes = 0;
		}
		if (usedMinutes > maxWorkTime) {
			usedMinutes = maxWorkTime;
		}
		return usedMinutes;
	}

	/**
	 * 功能： 获取当天工作时间总数（分钟数）
	 * 
	 * @param startWorkTime
	 * @param endWorkTime
	 * @return
	 * @throws ParseException
	 */
	public long getMaxWorkTimeAsMinutes(String _startWorkTime , String _endWorkTime) throws ParseException{
		String startWorkTime = _startWorkTime;
		String endWorkTime = _endWorkTime;
		//如果是日期+时间，则取日期的时间部分
		if(_startWorkTime!=null && _startWorkTime.length()>10 && _startWorkTime.split(" ").length==2){
			startWorkTime = _startWorkTime.split(" ")[1];
		}
		if(_endWorkTime!=null && _endWorkTime.length()>10 && _endWorkTime.split(" ").length==2){
			endWorkTime = _endWorkTime.split(" ")[1];
		}
		long maxWorkTimeAsMinutes = 0;
		// 1、按每天工作开始时间，结束时间来计算总体的工作时间
		//看看时间段是否超出工作时间了
		if(DateFormatUtil.formatDate(this.startWorkTime).after(DateFormatUtil.formatDate(startWorkTime))){
			startWorkTime = this.startWorkTime;
		}
		if(DateFormatUtil.formatDate(endWorkTime).after(DateFormatUtil.formatDate(this.endWorkTime))){
			endWorkTime = this.endWorkTime;
		}		
		maxWorkTimeAsMinutes = dateOperation.getDeff(startWorkTime, endWorkTime);		
		// 2、按休息的时间段来除去休息时间
		if(this.forRestTimeQuantumOfDay_List!=null&&this.forRestTimeQuantumOfDay_List.size()>0){
			Sys_holidayconf timeQuantumOfDay = null;
			for(int i=0;i<forRestTimeQuantumOfDay_List.size();i++){
				long restTime = 0;
				timeQuantumOfDay = (Sys_holidayconf) forRestTimeQuantumOfDay_List.get(i);
				// 看看这个休息时间段是否包含在计算时间之内
				if(DateFormatUtil.formatDate(timeQuantumOfDay.getStarttime()).after(DateFormatUtil.formatDate(startWorkTime))){
					if(DateFormatUtil.formatDate(endWorkTime).after(DateFormatUtil.formatDate(timeQuantumOfDay.getEndtime()))){
						// 说明休息时间完全被包含
						restTime = dateOperation.getDeff(timeQuantumOfDay.getStarttime(), timeQuantumOfDay.getEndtime());
					}else{
						// 说明结束时间在休息时间结束之前，结果应该这休息时段开始时间到计算结束时间之间的时间
						restTime = (int)(DateFormatUtil.formatDate(endWorkTime).getTime() - DateFormatUtil.formatDate(timeQuantumOfDay.getStarttime()).getTime())/(1000*60);
					}
				}else{
					if(DateFormatUtil.formatDate(endWorkTime).after(DateFormatUtil.formatDate(timeQuantumOfDay.getEndtime()))){
						// 说明结束时间在休息时间结束之后，结果应该是计算开始时间，到休息时段结束时间之间的时间
						restTime = (int)(DateFormatUtil.formatDate(timeQuantumOfDay.getEndtime()).getTime() - DateFormatUtil.formatDate(startWorkTime).getTime())/(1000*60);
					}else{
						//说明计算时间被包含在休息时间之内,不用计算
						restTime = 0;
					}
				}
				if(restTime<0){
					restTime = 0;
				}
				maxWorkTimeAsMinutes = maxWorkTimeAsMinutes - restTime;
			}
		}
		return maxWorkTimeAsMinutes;
	}

	/**
	 * 功能： 获取当天工作时间总数（分钟数）
	 * 
	 * @param startWorkTime
	 * @param endWorkTime
	 * @return
	 * @throws ParseException
	 */
	public long getMaxWorkTimeAsMinutes() throws ParseException {
		String startWorkTime = this.startWorkTime;
		String endWorkTime = this.endWorkTime;
		long maxWorkTimeAsMinutes = 0;
		// 1、按每天工作开始时间，结束时间来计算总体的工作时间
		maxWorkTimeAsMinutes = dateOperation.getDeff(startWorkTime, endWorkTime);
		// 2、按休息的时间段来除去休息时间
		if (this.forRestTimeQuantumOfDay_List != null&& this.forRestTimeQuantumOfDay_List.size() > 0) {
			Sys_holidayconf timeQuantumOfDay = null;
			for (int i = 0; i < forRestTimeQuantumOfDay_List.size(); i++) {
				timeQuantumOfDay = (Sys_holidayconf) forRestTimeQuantumOfDay_List.get(i);
				maxWorkTimeAsMinutes = maxWorkTimeAsMinutes - dateOperation.getDeff(timeQuantumOfDay.getStarttime(), timeQuantumOfDay.getEndtime());	
			}
		}
		return maxWorkTimeAsMinutes;
	}

	/**
	 * @return startWorkTime 开始工作时间， 如：08:00:00
	 */
	public String getStartWorkTime() {
		return startWorkTime;
	}

	/**
	 * @param startWorkTime
	 *            开始工作时间， 如：08:00:00
	 */
	public void setStartWorkTime(String startWorkTime) {
		this.startWorkTime = startWorkTime;
	}

	/**
	 * @return endWorkTime 结束工作时间， 如：17:30:00
	 */
	public String getEndWorkTime() {
		return endWorkTime;
	}

	/**
	 * @param endWorkTime
	 *            结束工作时间， 如：17:30:00
	 */
	public void setEndWorkTime(String endWorkTime) {
		this.endWorkTime = endWorkTime;
	}

	/**
	 * @return forRestTimeQuantumOfDay_List<TimeQuantumOfDay> 休息时间短
	 */
	public List<Sys_holidayconf> getForRestTimeQuantumOfDay_List() {
		return forRestTimeQuantumOfDay_List;
	}

	/**
	 * @param forRestTimeQuantumOfDay_List
	 *            <TimeQuantumOfDay> 休息时间短
	 */
	public void setForRestTimeQuantumOfDay_List(
			List<Sys_holidayconf> forRestTimeQuantumOfDay_List) {
		this.forRestTimeQuantumOfDay_List = forRestTimeQuantumOfDay_List;
	}
}
